#include "../include/memory_pool.h"

namespace sgi_memo_pool{

char* MemoryPool::start_free=nullptr;
char* MemoryPool::end_free=nullptr;
size_t MemoryPool::heap_size=0;

MemoryPool::Obj* volatile MemoryPool::free_list[FREE_LIST]={
    nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 
    nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
};

void* MemoryPool::allocate(size_t n){
    if(n>(size_t)MAX_BYTES){
        return  malloc(n);
    }

    // Obj* volatile* my_free_list是一个二级指针。它的结构可以这样理解：
    //     从右到左看
    //     my_free_list是一个指针，指向了另一个指针
    //     这个中间指针是volatile修饰的，表示它可能会被程序控制流以外的因素修改
    //     最终这个中间指针指向了一个Obj类型的对象

    // Obj* volatile* my_free_list的精确解析：
    //     这是一个指针指向指针的结构（二级指针），具体分解：
    //     my_free_list本身是一个指针（最右边的*决定）
    //     my_free_list指向的是一个Obj* volatile类型
    //     Obj* volatile是一个被volatile修饰的指针，指向Obj
    //     所以：
    //     my_free_list不是可变的，它本身是一个普通指针
    //     volatile修饰的是my_free_list所指向的那个指针
    Obj* volatile* my_free_list=free_list+freelist_index(n);
    Obj* result=*my_free_list;
    if(result==nullptr){
        void* r=refill(round_up(n));
        return r;
    }
    *my_free_list=result->free_list_link;
    return result;
}

void  MemoryPool::deallocate(void* p,size_t n){
    if(n>MAX_BYTES){
        free(p);
        return;
    }
    Obj* volatile* my_free_list=free_list+freelist_index(n);
    
    Obj* q = (Obj*)p; // 将待释放内存块转换为Obj类型

    q->free_list_link=*my_free_list;
    *my_free_list=q;
    return;
}

void* MemoryPool::reallocate(void* p,size_t old_sz,size_t new_sz){
    if(old_sz>(size_t) MAX_BYTES||new_sz>(size_t)MAX_BYTES){
        return realloc(p,new_sz);
    }
    if(old_sz==new_sz) return p;
    //判断old_sz 和new_sz大小  如果old_sz大则拷贝大小以new_sz为主
    size_t copy_size= old_sz > new_sz ? new_sz : old_sz;
    void* q= allocate(new_sz);
    memcpy(q,p,copy_size);
    deallocate(p,old_sz);
    return q;

}


void* MemoryPool::refill(size_t n){
    int nobj=20;
    char *chunk=chunk_alloc(n,nobj);
    Obj* volatile* my_free_list;
    Obj* current_obj, *next_obj, *result;
    int i;
    result=(Obj*) chunk;
    my_free_list=free_list+freelist_index(n);// 未写出
    *my_free_list=next_obj=current_obj=(Obj*)(chunk+n);
    for(i=1;;i++){
        current_obj=next_obj;
        if(i==nobj-1){
            current_obj->free_list_link=nullptr;
            break;
        }
        next_obj=(Obj*)((char*)next_obj +n);
        current_obj->free_list_link=next_obj;
    }
    
    //逻辑错误
    // *my_free_list=current=next=(Obj*) ((char*) chunk +n);
    // for( i=0;;i++){
    //     Obj* p=(Obj*) ((char*)next+n);
    //     if(i==nobj-1){
    //         next->free_list_link=nullptr;
    //         break;
    //     }else{
    //         next->free_list_link=p;
    //     }
    //     next=next->free_list_link;
    // }

    return result;

}

char* MemoryPool::chunk_alloc(size_t size,int& nobjs){
    char* result;
    size_t total_bytes=size * nobjs;
    size_t bytes_left =end_free-start_free;
    if(bytes_left>=total_bytes){
        result=start_free;
        start_free=start_free+total_bytes;
        return result;
    }else if(bytes_left>size){
        // size_t real=bytes_left/size; 需要修改nobjs的值。
        nobjs=bytes_left/size; 
        result=start_free;
        start_free=start_free+nobjs*size;
        return result;
    }
    else{
        size_t bytes_to_get=2*total_bytes+round_up(heap_size>>4);
        //这行代码添加随堆大小增长的附加量是一种自适应增长策略，有几个关键优势：
            // 减少分配频率 - 随着程序运行，内存使用量通常会增加。通过让新分配的内存量随已分配内存增长，可以减少向系统请求内存的频率
            // 分摊开销 - 系统内存分配有固定开销，通过每次多分配一些，可以分摊这些开销到更多的对象上
            // 自适应性 - 将增量设为堆大小的一小部分(heap_size >> 4，即除以16)让内存池根据应用实际使用模式动态调整增长速率
            // 防止碎片化 - 较少但较大的分配比频繁的小分配产生更少的外部碎片
            // 本质上，这是一种启发式优化，通过预测未来内存需求会随着已用内存增加而增加，从而提高内存分配效率。
        
        if(bytes_left>0){
            Obj* volatile* my_free_list=free_list+freelist_index(bytes_left);
            Obj* current_obj=(Obj*) start_free;
            current_obj->free_list_link=*my_free_list;
            *my_free_list=current_obj;
        }
        start_free=(char*)malloc(bytes_to_get);
        if(start_free==nullptr){
            int i;
            Obj* volatile* my_free_list;
            Obj* cur;
            
            for(i=size;i<MAX_BYTES;i+=ALIGN){
                my_free_list=free_list+freelist_index(i);
                if(*my_free_list!=nullptr){
                    cur=*my_free_list;
                    *my_free_list=cur->free_list_link;
                    //没写出来
                    start_free=(char*) cur;
                    //end_free=(char*) cur->free_list_link;  错误，表达错误;
                    end_free=start_free+i;
                    return chunk_alloc(size,nobjs); //重点
                    //没写出来
                }
            }
            
            start_free=nullptr; //没想出来
            start_free=(char*)malloc(bytes_to_get);
            if(start_free==nullptr){
                throw std::bad_alloc();
            }
        }
        
        heap_size+=bytes_to_get;//忽视
        end_free=start_free+bytes_to_get;
        return chunk_alloc(size,nobjs); //重点
    }  
}


}